<template>
  <mescroll-body
    @init="mescrollInit"
    @down="downCallback"
    @up="upCallback"
    safearea
    :down="downConfig"
    :up="upConfig"
    class="md-page-list">
    <slot />
  </mescroll-body>
</template>

<script setup lang="ts">
import { reactive, onUnmounted, ref } from 'vue';
import { onPageScroll, onReachBottom, onShow } from '@dcloudio/uni-app';
// 组件
import useMescroll from '@/uni_modules/mescroll-uni/hooks/useMescroll.js';

// 使用ref来跟踪组件是否被销毁
const isDestroyed = ref(false);
const { mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);

// 自定义下拉刷新回调
const downCallback = (mescroll: any) => {
  // 检查组件是否已被销毁
  if (isDestroyed.value) {
    return;
  }

  // 先回到页面顶部
  // mescroll.scrollTo(0, 300);

  // 延迟执行刷新，确保滚动动画完成
  setTimeout(() => {
    if (isDestroyed.value) return;

    if (mescroll.optUp.use) {
      mescroll.resetUpScroll();
    } else {
      setTimeout(() => {
        if (isDestroyed.value) return;
        mescroll.endSuccess();
      }, 500);
    }
  }, 350);
};

const data = reactive({
  canReset: false,
  list: [],
  params: {} as Record<string, any>,
  lastResetParams: '', // 记录上次重置的参数，避免重复重置
  resetTimer: null as any, // 防抖定时器
  isLoading: false, // 是否正在加载
  hasMore: true, // 是否还有更多数据
});

const props = defineProps({
  // 给到list的父级就行，如果只有一层list，默认不用传
  pathname: {
    type: Array as () => string[],
    default: [],
  },
  api: Function,
  params: Object,
  resKey: {
    type: String,
    default: 'list',
  },
});

const emit = defineEmits(['change']);

// 下拉刷新配置
const downConfig = {
  offset: 120, // 下拉距离超过120px才触发刷新
  startTop: 50, // 必须在距离顶部50px以内才能触发下拉刷新
  minAngle: 45, // 向下滑动最少偏移的角度
  inOffsetRate: 0.8, // 下拉距离小于offset时的高度变化比例
  outOffsetRate: 0.2, // 下拉距离大于offset时的高度变化比例
  beforeLoading: (mescroll: any) => {
    // 检查组件是否已被销毁
    if (isDestroyed.value) {
      return true; // 阻止下拉刷新
    }

    // 检查是否在页面顶部，如果不在顶部则不允许下拉刷新
    const scrollTop = mescroll.getScrollTop();
    if (scrollTop > 50) {
      // 不在顶部时，提示用户先回到顶部
      uni.showToast({
        title: '请先回到页面顶部',
        icon: 'none',
        duration: 1500,
      });
      return true; // 返回true阻止下拉刷新
    }
    return false; // 允许下拉刷新
  },
};

// 上拉加载配置
const upConfig = {
  offset: 150, // 距离底部150px时触发加载
  noMoreSize: 5, // 列表数据少于5条时不显示"无更多数据"
  auto: false, // 禁用自动加载第一页
};

const _getArrayToObjPointValue = (obj: Record<string, any>, pathname: string[]) => {
  return pathname.reduce((acc: any, curr: string) => {
    return acc && acc[curr];
  }, obj);
};

// 刷新页面
const onRefresh = (params: Record<string, any>) => {
  data.params = { ...params };
  // 更新重置参数记录
  data.lastResetParams = JSON.stringify(data.params);
  // 重置加载状态
  data.isLoading = false;
  data.hasMore = true;
  getMescroll().resetUpScroll(); // 重置列表数据为第一页
  getMescroll().scrollTo(0, 0); // 重置列表数据为第一页时,建议把滚动条也重置到顶部,避免无法再次翻页的问题
};

// 直接暴露方法给父组件调用（无需return，在<script setup>中自动暴露）
defineExpose({
  onRefresh,
  // 手动控制空布局显示
  showEmpty: () => {
    const mescroll = getMescroll();
    if (mescroll) {
      mescroll.showEmpty();
    }
  },
  // 手动隐藏空布局
  hideEmpty: () => {
    const mescroll = getMescroll();
    if (mescroll) {
      mescroll.removeEmpty();
    }
  },
});

/**
 * 接口相关
 */
// 分页处理
// 上拉加载的回调: 其中num:当前页 从1开始, size:每页数据条数,默认10
const upCallback = async (mescroll: any) => {
  // 检查组件是否已被销毁
  if (isDestroyed.value) {
    return;
  }

  // 防止重复加载
  if (data.isLoading) {
    return;
  }

  // 检查API是否存在
  if (!props.api) {
    return;
  }

  // 检查组件是否仍然可见（防止tab切换后仍然调用API）
  if (!mescroll || !mescroll.getScrollTop || typeof mescroll.getScrollTop !== 'function') {
    return;
  }

  // 简化的可见性检查 - 只检查基本的API和加载状态
  data.isLoading = true;

  try {
    // 再次检查组件是否已被销毁
    if (isDestroyed.value) {
      return;
    }

    let res = await props.api({
      page: mescroll.num,
      limit: mescroll.size,
      ...props.params,
      ...data.params,
    });

    // 检查组件是否已被销毁
    if (isDestroyed.value) {
      return;
    }

    let obj = res?.data;
    if (props.pathname.length > 0) {
      obj = _getArrayToObjPointValue(res?.data, props.pathname);
    }
    const curPageData = obj?.[props.resKey] || []; // 当前页数据
    const total = obj?.total || 0;

    if (mescroll.num == 1) {
      data.list = []; // 第一页需手动制空列表
      data.hasMore = true; // 重置加载更多状态
    }

    data.list = data.list.concat(curPageData); //追加新数据

    // 修复空布局显示问题：只有当第一页完全没有数据时才显示空布局
    if (mescroll.num == 1 && curPageData.length === 0) {
      // 第一页完全没有数据，显示空布局
      mescroll.endSuccess(0, false);
    } else if (curPageData.length > 0 && data.list.length < total) {
      // 还有更多数据
      data.hasMore = true;
      mescroll.endByPage(curPageData.length, total);
    } else if (curPageData.length > 0) {
      // 当前页有数据，但没有更多页了
      data.hasMore = false;
      mescroll.endSuccess(curPageData.length, false);
    } else {
      // 当前页没有数据，且不是第一页
      data.hasMore = false;
      mescroll.endSuccess(0, false);
    }

    // 回调给父组件渲染用的数据
    if (!isDestroyed.value) {
      emit('change', data.list);
    }
  } catch (e) {
    console.error('分页加载失败:', e);
    if (!isDestroyed.value && mescroll && typeof mescroll.endErr === 'function') {
      mescroll.endErr(); // 请求失败, 结束加载
      // 回调给父组件渲染用的数据
      emit('change', []);
      data.list = [];
    }
  } finally {
    if (!isDestroyed.value) {
      data.isLoading = false;
    }
  }
};

onShow(() => {
  // 检查组件是否已被销毁
  if (isDestroyed.value) {
    return;
  }

  // 检查API是否存在，如果不存在则不执行任何逻辑
  if (!props.api) {
    return;
  }

  // 只有在需要重置且当前组件可见时才重置
  if (data.canReset && data.params && Object.keys(data.params).length > 0) {
    // 检查当前组件是否在视图中
    const isVisible = uni.getSystemInfoSync().windowHeight > 0;
    if (isVisible) {
      // 比较当前参数与上次重置的参数，避免重复重置
      const currentParamsStr = JSON.stringify(data.params);
      if (currentParamsStr !== data.lastResetParams) {
        // 清除之前的定时器
        if (data.resetTimer) {
          clearTimeout(data.resetTimer);
        }
        // 防抖处理，延迟100ms执行重置
        data.resetTimer = setTimeout(() => {
          // 再次检查组件是否已被销毁
          if (isDestroyed.value) {
            return;
          }

          const mescroll = getMescroll();
          if (mescroll && !isDestroyed.value) {
            mescroll.resetUpScroll(); // 重置列表数据为第一页
            mescroll.scrollTo(0, 0); // 重置列表数据为第一页时,建议把滚动条也重置到顶部,避免无法再次翻页的问题
            data.lastResetParams = currentParamsStr; // 记录本次重置的参数
          }
          data.resetTimer = null;
        }, 100);
      }
    }
  }
  data.canReset = true; // 过滤第一次的onShow事件,避免初始化界面时重复触发upCallback, 无需配置auto:false
});

// 组件销毁时清理定时器
onUnmounted(() => {
  isDestroyed.value = true; // 标记组件已销毁

  // 清理定时器
  if (data.resetTimer) {
    clearTimeout(data.resetTimer);
    data.resetTimer = null;
  }

  // 清理数据
  data.list = [];
  data.params = {};
  data.lastResetParams = '';
  data.isLoading = false;
  data.hasMore = true;

  // 尝试清理mescroll实例
  try {
    const mescroll = getMescroll();
    if (mescroll && typeof mescroll.destroy === 'function') {
      mescroll.destroy();
    }
  } catch (e) {
    console.log('清理mescroll实例失败:', e);
  }
});
</script>

<style lang="scss" scoped></style>
